//
//  GZLogManager.m
//  GZLogger
//
//  Created by GR on 2018/12/20.
//  Copyright © 2018 GR. All rights reserved.
//

#import "GZLogManager.h"
#import "GZLogItem.h"
#import "GZLogger.h"

@interface GZLogManager ()

@property (nonatomic, strong) NSMutableArray<id<GZLogger>> *loggers;

@property (nonatomic, strong) dispatch_queue_t ioQueue;

@end

@implementation GZLogManager

+ (instancetype)sharedInstance {
    
    static GZLogManager *instance = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        instance = [[GZLogManager alloc] init];
    });
    return instance;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.ioQueue = dispatch_queue_create("com.gztool.gzlogger.gzlogmanager", DISPATCH_QUEUE_SERIAL);
    }
    return self;
}

#pragma mark - Private

- (NSMutableArray *)loggers {
    if (!_loggers) {
        _loggers = [NSMutableArray array];
    }
    return _loggers;
}

- (void)addLogger:(id<GZLogger>)logger {
    
    NSParameterAssert(logger);
    NSParameterAssert([logger conformsToProtocol:@protocol(GZLogger)]);
    
    dispatch_async(self.ioQueue, ^{
        [self.loggers addObject:logger];
    });
    
}

- (void)removeLogger:(id<GZLogger>)logger {
    [self.loggers removeObject:logger];
}

- (NSArray<id<GZLogger>> *)allLoggers {
    return self.loggers.copy;
}

- (void)recordWithItem:(GZLogItem *)item {
    
    for (id<GZLogger> logger in self.loggers) {
        [logger recordLogItem:item];
    }
}

#pragma mark - Public
- (void)recordWithLevel:(GZLogLevel)level
                    tag:(NSString *)tag
                   file:(NSString *)file
               function:(NSString *)function
                   line:(NSUInteger)line
                content:(NSString *)content
             stackLevel:(NSUInteger)stackLevel
           dataFileName:(NSString *)dataFileName {
    
    GZLogItem *item = [GZLogItem itemWithTimestamp:[NSDate date].timeIntervalSince1970
                                              file:file
                                              line:line
                                          function:function
                                             level:level
                                               tag:tag
                                           content:content
                                        stackLevel:stackLevel
                                      dataFileName:dataFileName];
    [self recordWithItem:item];
}



@end
